package com.example.word.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.word.dto.UserDetailDTO;
import com.example.word.dto.UserInfoDTO;
import com.example.word.dto.UserOnlineDTO;
import com.example.word.enums.FileExtEnum;
import com.example.word.enums.FilePathEnum;
import com.example.word.exception.BizException;
import com.example.word.mapper.UserAuthMapper;
import com.example.word.mapper.UserRoleMapper;
import com.example.word.pojo.UserAuth;
import com.example.word.pojo.UserInfo;
import com.example.word.pojo.UserRole;
import com.example.word.service.RedisService;
import com.example.word.service.RoleService;
import com.example.word.service.UserInfoService;
import com.example.word.mapper.UserInfoMapper;
import com.example.word.service.UserRoleService;
import com.example.word.strategy.context.UploadStrategyContext;
import com.example.word.util.BeanCopyUtils;
import com.example.word.util.PageUtils;
import com.example.word.util.UserUtils;
import com.example.word.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static com.example.word.constant.RedisPrefixConst.USER_CODE_KEY;
import static com.example.word.util.PageUtils.getLimitCurrent;
import static com.example.word.util.PageUtils.getSize;

/**
 *
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
    implements UserInfoService{

    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private RedisService redisService;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private UserAuthMapper userAuthMapper;
    @Autowired
    private SessionRegistry sessionRegistry;
    @Autowired
    private UploadStrategyContext uploadStrategyContext;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUserInfo(UserInfoVO userInfoVO) {
        UserInfo userInfo = UserInfo.builder()
                .id(UserUtils.getLoginUser().getUserInfoId())
                .faculty(userInfoVO.getFaculty())
                .nickname(userInfoVO.getNickname())
                .age(userInfoVO.getAge())
                .sex(userInfoVO.getSex())
                .address(userInfoVO.getAddress())
                .phone(userInfoVO.getPhone())
                .sno(userInfoVO.getSno())
                .build();
        userInfoMapper.updateById(userInfo);

    }

    @Override
    public void saveUserEmail(EmailVO emailVO) {
        if(!emailVO.getCode().equals(redisService.get(USER_CODE_KEY + emailVO.getEmail()).toString())){
            throw new BizException("验证码错误");
        }
        UserInfo userInfo = UserInfo.builder()
                .id(UserUtils.getLoginUser().getUserInfoId())
                .email(emailVO.getEmail())
                .build();
        userInfoMapper.updateById(userInfo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUserStatus(UserStatusVO userStatusVO) {
        UserInfo userInfo = UserInfo.builder()
                .id(userStatusVO.getId())
                .status(userStatusVO.getStatus())
                .build();
        userInfoMapper.updateById(userInfo);
    }


    @Override
    public void updateUserRole(UserRoleVO userRoleVO) {
        // 更新用户角色和昵称
        UserInfo userInfo = UserInfo.builder()
                .id(userRoleVO.getUserInfoId())
                .nickname(userRoleVO.getNickname())
                .faculty(userRoleVO.getFaculty())
                .status(userRoleVO.getStatus())
                .build();
        userInfoMapper.updateById(userInfo);
        userRoleService.remove(new LambdaQueryWrapper<UserRole>()
                .eq(UserRole::getUserId, userRoleVO.getUserInfoId()));
        List<UserRole> userRoleList = userRoleVO.getRoleIdList().stream()
                .map(roleId -> UserRole.builder()
                        .roleId(roleId)
                        .userId(userRoleVO.getUserInfoId())
                        .build())
                .collect(Collectors.toList());
        userRoleService.saveBatch(userRoleList);

    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteUsers(List<Integer> userInfoIdList) {
        userRoleMapper.delete(new LambdaQueryWrapper<UserRole>()
        .in(UserRole::getUserId, userInfoIdList));
        userAuthMapper.delete(new LambdaQueryWrapper<UserAuth>()
        .in(UserAuth::getUserInfoId, userInfoIdList));
        userInfoMapper.deleteBatchIds(userInfoIdList);
    }

    @Override
    public String updateUserAvatar(MultipartFile file) {
        //头像上传
        String avatar = uploadStrategyContext.executeUploadStrategy(file, FilePathEnum.AVATAR.getPath());
        //更新用户信息
        System.out.println(UserUtils.getLoginUser().getId());
        UserInfo userInfo = UserInfo.builder()
                .id(UserUtils.getLoginUser().getUserInfoId())
                .avatar(avatar)
                .build();
        userInfoMapper.updateById(userInfo);
        return avatar;
    }

    @Override
    public UserInfoDTO getUserInfoById(Integer userId) {

        return BeanCopyUtils.copyObject(userInfoMapper.selectById(userId), UserInfoDTO.class);
    }
    @Override
    public PageResult<UserOnlineDTO> listOnlineUsers(ConditionVO conditionVO) {
        // 获取security在线session
        List<UserOnlineDTO> userOnlineDTOList = sessionRegistry.getAllPrincipals().stream()
                .filter(item -> sessionRegistry.getAllSessions(item, false).size() > 0)
                .map(item -> JSON.parseObject(JSON.toJSONString(item), UserOnlineDTO.class))
                .filter(item -> StringUtils.isBlank(conditionVO.getKeywords()) || item.getNickname().contains(conditionVO.getKeywords()))
                .sorted(Comparator.comparing(UserOnlineDTO::getLastLoginTime).reversed())
                .collect(Collectors.toList());
        // 执行分页
        int fromIndex = getLimitCurrent().intValue();
        int size = getSize().intValue();
        int toIndex = userOnlineDTOList.size() - fromIndex > size ? fromIndex + size : userOnlineDTOList.size();
        List<UserOnlineDTO> userOnlineList = userOnlineDTOList.subList(fromIndex, toIndex);
        return new PageResult<>(userOnlineList, userOnlineDTOList.size());
    }

    @Override
    public void removeOnlineUser(Integer userInfoId) {
        // 获取用户session
        List<Object> userInfoList = sessionRegistry.getAllPrincipals().stream().filter(item -> {
            UserDetailDTO userDetailDTO = (UserDetailDTO) item;
            return userDetailDTO.getUserInfoId().equals(userInfoId);
        }).collect(Collectors.toList());
        List<SessionInformation> allSessions = new ArrayList<>();
        userInfoList.forEach(item -> allSessions.addAll(sessionRegistry.getAllSessions(item, false)));
        // 注销session
        allSessions.forEach(SessionInformation::expireNow);
    }
}




